/*
 *  masslinkchain.cpp
 *  EPPI-0.0
 *
 *  Created by Juan Carlos Garcia Orden on 29/03/12
 *
 */

#include "masslinkchain.h"

// Constructor with material
MassLinkChain::MassLinkChain(ifstream &in, string cname, string matnam, double ar, vector<string> &allPoints, MecSystem *pSys)
:	Body(in,cname,pSys),
	firstP(),
	secondP(),
	matName(matnam),
	area(ar),
	connectSurface()
{	
	dim = parentSystem->dim;	/** Must be set always.  dim belongs to the mother class Body */
	type = "masslinkchain";
	
	int i;
	vector<string> auxsv(2);
	
	for (i=0; i<allPoints.size()-1; ++i)
	{
		auxsv[0] = allPoints[i];
		auxsv[1] = allPoints[i+1];
		vComponents.push_back(new MassLink(auxsv,area,matName,dim));
		connectSurface.push_back(auxsv);
	}

	vPointNamesSurface = allPoints;
	
	char keyword[20];
	string auxs;				/** Aux string */
	char contactFileName[30];
	int numContact;
	string line;
	vector<string> vPNames;
	ifstream inContact;	

	while (in >> keyword && strcmp(keyword,"ENDBODY") )
	{
		if (!strcmp(keyword,"CONTACTPOINTS"))
		{
			in >> auxs;
			if (!auxs.compare("all"))	contactAllOption = true;
			if (!auxs.compare("file"))
			{
				in >> contactFileName;
				contactFileOption = true;
			}
			if (!auxs.compare("names"))
			{
				contactNamesOption = true;
				getline(in,line);
				istringstream iss(line);
				while (iss >> keyword )
				{
					auxs = keyword;
					vPNames.push_back(auxs);
					//cout << "keyword is " << keyword << endl;
				}				
			}			
		}
	}
	// If nothing is said about contact, take by default the "all" option
	if (contactAllOption==false && contactFileOption==false && contactNamesOption==false)	contactAllOption = true;
	
	if (contactAllOption==true)
	{
		vPointNamesContact = vPointNamesSurface;
	}
	if (contactFileOption==true)
	{
		inContact.open(contactFileName);
		inContact >> numContact;
		for (i=0; i<numContact; ++i)
		{
			inContact >> auxs;
			vPointNamesContact.push_back(auxs);
		}
		inContact.close();
	}
	if (contactNamesOption==true)
	{
		for (i=0; i<vPNames.size(); ++i)	vPointNamesContact.push_back(vPNames[i]);
	}	
}

// ***
// Constructor with mass
MassLinkChain::MassLinkChain(ifstream &in, string cname, double masa, vector<string> &allPoints, MecSystem *pSys)
:	Body(in,cname,pSys),
firstP(),
secondP(),
matName(),
area(),
connectSurface()
{	
	dim = parentSystem->dim;	/** Must be set always.  dim belongs to the mother class Body */
	type = "MassLinkChain";
	
	int i;
	vector<string> auxsv(2);
	double masaOnePiece = masa/(allPoints.size()-1);
	
	for (i=0; i<allPoints.size()-1; ++i)
	{
		auxsv[0] = allPoints[i];
		auxsv[1] = allPoints[i+1];
		vComponents.push_back(new MassLink(auxsv,masaOnePiece,dim));
		connectSurface.push_back(auxsv);
	}
	
	vPointNamesSurface = allPoints;
	
	char keyword[20];
	string auxs;				/** Aux string */
	char contactFileName[30];
	int numContact;
	string line;
	vector<string> vPNames;
	ifstream inContact;	
	
	while (in >> keyword && strcmp(keyword,"ENDBODY") )
	{
		if (!strcmp(keyword,"CONTACTPOINTS"))
		{
			in >> auxs;
			if (!auxs.compare("all"))	contactAllOption = true;
			if (!auxs.compare("file"))
			{
				in >> contactFileName;
				contactFileOption = true;
			}
			if (!auxs.compare("names"))
			{
				contactNamesOption = true;
				getline(in,line);
				istringstream iss(line);
				while (iss >> keyword )
				{
					auxs = keyword;
					vPNames.push_back(auxs);
					//cout << "keyword is " << keyword << endl;
				}				
			}			
		}
	}
	// If nothing is said about contact, take by default the "all" option
	if (contactAllOption==false && contactFileOption==false && contactNamesOption==false)	contactAllOption = true;
	
	if (contactAllOption==true)
	{
		vPointNamesContact = vPointNamesSurface;
	}
	if (contactFileOption==true)
	{
		inContact.open(contactFileName);
		inContact >> numContact;
		for (i=0; i<numContact; ++i)
		{
			inContact >> auxs;
			vPointNamesContact.push_back(auxs);
		}
		inContact.close();
	}
	if (contactNamesOption==true)
	{
		for (i=0; i<vPNames.size(); ++i)	vPointNamesContact.push_back(vPNames[i]);
	}	
}

// ***

void MassLinkChain::setPTPointsComp()
{
	int j, k;
	vector<string> auxs;
	map<string, Point*, less<string> > maux;
	pair<string,Point*> mauxEntry;
	pair<string,int> sharedEntry;
	
	for(j=0; j<vComponents.size(); j++)		
	//Loop on the components
	{
		auxs = (vComponents[j]->getPointNames());
		for(k=0; k<auxs.size(); k++)		
		// Loop on the names of the points within each component
		{
			/** If the point it is not at the local process ... */
			if( (parentSystem->checkIfPointProcess(auxs[k]))==false )
			{
				/** ...  create it at root system, copying the original point from the remote process */
				parentSystem->createPointAtRoot( parentSystem->getPTPoint(auxs[k]) );
				/** ...  and add the name of the shared point at the remote process */
				parentSystem->addRemoteSharedPoint(auxs[k],parentSystem->getProcNum());
			}
			mauxEntry.first = auxs[k];
			mauxEntry.second = (parentSystem->getPTPointLocal(auxs[k]));
			maux.insert(mauxEntry);
		}
		vComponents[j]->setMPoints(maux);
		maux.clear();
	}
}

// ***

void MassLinkChain::setPTPointsLoad()
{
	int j, k;
	vector<string> auxs;
	map<string, Point*, less<string> > maux;
	pair<string,Point*> mauxEntry;
	pair<string,int> sharedEntry;
	
	for(j=0; j<vLoads.size(); j++)		
	//Loop on the Loads
	{
		auxs = (vLoads[j]->getPointNames());
		for(k=0; k<auxs.size(); k++)		
		// Loop on the names of the points within each component
		{
			/** If the point it is not at the local process ... */
			if( (parentSystem->checkIfPointProcess(auxs[k]))==false )
			{
				/** ...  create it at root system, copying the original point from the remote process */
				parentSystem->createPointAtRoot( parentSystem->getPTPoint(auxs[k]) );
				/** ...  and add the name of the shared point at the remote process */
				parentSystem->addRemoteSharedPoint(auxs[k],parentSystem->getProcNum());
			}
			mauxEntry.first = auxs[k];
			mauxEntry.second = (parentSystem->getPTPointLocal(auxs[k]));
			maux.insert(mauxEntry);
		}
		vLoads[j]->setMPoints(maux);
		maux.clear();
	}

}

// ***

void MassLinkChain::setPPointSurface()
{	
	// Build the vector of pointers to the surface points
	vPPointSurface.resize(vPointNamesSurface.size());
	
	int i;
	string auxs;
	//vector<Point*>	vPoints(nNodes);	
	for(i=0;i<vPointNamesSurface.size();i++)
	{
		auxs = vPointNamesSurface[i];
		if(checkForSlash(auxs)==false)	addSystemName(auxs,parentSystem->name);
		vPPointSurface[i] = parentSystem->getPTPointLocal( auxs ); 
	}			
}

// ***

void MassLinkChain::setMatAtComp()
{
	int i;
	string matName;
	Material* mat;
	for(i=0; i<vComponents.size(); i++)
	{
		matName = vComponents[i]->getMatName();
		mat = parentSystem->getPTMaterial(matName);		
		vComponents[i]->setMatAtComp(mat);
	}
}

// ***

void MassLinkChain::getBoundary(vector<vector<string> >& connect)
{
/*
	cout << "Estos son los puntos ordenados \n";
	 int i;
	 for(i=0; i<vPointNamesSurface.size(); ++i)	cout << vPointNamesSurface[i] << "\n";
	 
	cout << "Esta es la conectividad \n";
	for(i=0; i<connectSurface.size(); ++i)	cout << connectSurface[i][0] << "\t" << connectSurface[i][1] << "\n";
*/
}

// ***
/*
void MassLinkChain::writeFileGraph(ofstream &fGraph, string& gFormat)
{}	
*/
// ***

void MassLinkChain::writeMSH(ofstream &fGraph)
{}

// ***

void MassLinkChain::writeVTU(ofstream &fGraph, bool& plotDispFlag, bool& plotProcFlag, bool& plotStressFlag)
{
	int i;
	int j;
	int nt;
	double auxd;
	
	localFGraph << "<?xml version=\"1.0\"?>\n";
	localFGraph << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
	localFGraph << "	<UnstructuredGrid>\n";
	localFGraph << "		<Piece NumberOfPoints=\"" << vPointNamesSurface.size() << "\" NumberOfCells=\"" << connectSurface.size() << "\">\n";
	localFGraph << "			<Points>\n";
	localFGraph << "				<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">";
	for(i=0; i<vPPointSurface.size(); ++i)
	{
		localFGraph << "\n";
		localFGraph << "				";
		nt = vPPointSurface[i]->globalTNum.size();	// Number of translational dofs
		for (j=0; j<nt; ++j)
		{
			auxd = parentSystem->getDof( vPPointSurface[i]->globalTNum[j] );
			if (fabs(auxd)<= 1e-200) auxd = 0.0;
			localFGraph << auxd << "\t"; 
		}
		if (nt<2) localFGraph << 0.0;	// Second coordinate, just in case is 1D
		if (nt<3) localFGraph << "\t" << 0.0;	// Third coordinate, just in case is 2D
	}
	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph << "			</Points>\n";
	localFGraph<< "			<Cells>\n";
	localFGraph << "				<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">";
	for (i=0; i<connectSurface.size(); ++i)
	{
		localFGraph << "\n";
		localFGraph << "					";
		for (j=0; j<connectSurface[0].size() ; ++j) // edit
		{
			localFGraph << pNamePNumber[ connectSurface[i][j] ] << "\t";
		}
	}
	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph << "				<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">";
	localFGraph << "\n";
	localFGraph << "					";
	for (i=0; i<connectSurface.size(); ++i)
	{
		localFGraph << connectSurface[0].size()*(1+i) << "\t";
	}
	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph << "				<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">";
	localFGraph << "\n";
	localFGraph << "					";
	for (i=0; i<connectSurface.size(); ++i)
	{
		localFGraph << 3 << "\t";
	}
	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph<< "			</Cells>\n";
	// Example of pointData
	/*
	 localFGraph << "			<PointData Scalars=\"scalars\">\n";
	 localFGraph << "				<DataArray type=\"Float64\" Name=\"scalars\" format=\"ascii\">";
	 localFGraph << "\n";
	 for (i=0; i<vPPointSurface.size(); ++i)
	 {
	 localFGraph << 0.4 << "\n";
	 }
	 localFGraph << "				</DataArray>\n";
	 localFGraph << "			</PointData>\n";
	 */
	localFGraph << "		</Piece>\n";
	localFGraph << "	</UnstructuredGrid>\n";
	localFGraph << "</VTKFile>\n";		
}

// ***

void MassLinkChain::writeOOGL(ofstream &fGraph)
{}

// ***

void MassLinkChain::writeFileTemp(const double& time, ofstream & outF)
{}

// ***

void MassLinkChain::setIniPosBody(vector<double>& iniValues)
{}